﻿using Microsoft.VisualStudio.TestTools.UnitTesting;

using PublicDomain.Data.Csv;
using PublicDomain.Framework.UnitTesting.DataDrivenTest;

namespace PublicDomain.UnitTest.Data.Csv
{
    [TestClass]
    public class DelimitedStringTest
    {
        public TestContext TestContext { get; set; }

        public void TestInitialize()
        {
        }

        [TestMethod]
        [Description("Tests method DelimitedString.Split().")]
        [DeploymentItem("DelimitedStringTestData.mdb")]
        [DataSource("System.Data.OleDb", "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\\DelimitedStringTestData.mdb", "SplitTestData", DataAccessMethod.Sequential)]
        public void SplitTest()
        {
            var dataDrivenTest = new DataDrivenTest<SplitTestDataTestParams, SplitTestDataExpectedResults>(this.TestContext);

            dataDrivenTest.ExecuteTest(() =>
                {
                    var columns = DelimitedString.Split(dataDrivenTest.TestParams.DelimitedText, dataDrivenTest.TestParams.DelimiterChar, false);

                    Assert.AreEqual(columns[0], dataDrivenTest.ExpectedResults.Column1Text);
                    Assert.AreEqual(columns[1], dataDrivenTest.ExpectedResults.Column2Text);
                    Assert.AreEqual(columns[2], dataDrivenTest.ExpectedResults.Column3Text);
                });
        }

        [TestMethod]
        [Description("Tests method DelimitedString.RemovePrefix(this string text, string prefix).")]
        [DeploymentItem("DelimitedStringTestData.mdb")]
        [DataSource("System.Data.OleDb", "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\\DelimitedStringTestData.mdb", "TryRemovePrefixTestData", DataAccessMethod.Sequential)]
        public void RemovePrefixTest()
        {
            var dataDrivenTest = new DataDrivenTest<TryRemovePrefixTestDataTestParams, TryRemovePrefixTestDataExpectedResults>(this.TestContext);

            dataDrivenTest.ExecuteTest(() =>
            {
                string removedPrefixText;
                var actualRemoveResult = DelimitedString.TryRemovePrefix(dataDrivenTest.TestParams.Text, dataDrivenTest.TestParams.Prefix, out removedPrefixText);

                Assert.AreEqual(dataDrivenTest.ExpectedResults.RemoveResult, actualRemoveResult);
                Assert.AreEqual(dataDrivenTest.ExpectedResults.TextWithRemovedPrefix, removedPrefixText);
            });
        }

        [TestMethod]
        [Description("Tests method DelimitedString.ParseField(int fieldStartIndex, string delimitedText, char delimiter, out int nextFieldStartIndex)")]
        [DeploymentItem("DelimitedStringTestData.mdb")]
        [DataSource("System.Data.OleDb", "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\\DelimitedStringTestData.mdb", "ParseFieldTestData", DataAccessMethod.Sequential)]
        public void ParseFieldTest()
        {
            var dataDrivenTest = new DataDrivenTest<ParseFieldTestDataTestParams, ParseFieldTestDataExpectedResults>(this.TestContext);

            dataDrivenTest.ExecuteTest(() =>
            {
                int actualNextFieldStartIndex;
                var actualFieldText = DelimitedString_Accessor.ParseField(
                    dataDrivenTest.TestParams.FieldStartIndex,
                    dataDrivenTest.TestParams.DelimitedText,
                    dataDrivenTest.TestParams.DelimiterChar,
                    dataDrivenTest.TestParams.EscapedEmptyAsZeroLengthString,
                    out actualNextFieldStartIndex);

                var expectedFieldTextText = dataDrivenTest.ExpectedResults.ExpectedFieldTextText;
                expectedFieldTextText = expectedFieldTextText == "(null)" ? null : expectedFieldTextText;

                Assert.AreEqual(expectedFieldTextText, actualFieldText);
                Assert.AreEqual(dataDrivenTest.ExpectedResults.ExpectedNextFieldStartIndex, actualNextFieldStartIndex);
            });
        }

        [TestMethod]
        [Description("Tests method DelimitedString.ParseField(int fieldStartIndex, string delimitedText, char delimiter, out int nextFieldStartIndex)")]
        [DeploymentItem("DelimitedStringTestData.mdb")]
        [DataSource("System.Data.OleDb", "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\\DelimitedStringTestData.mdb", "QuatedToUnquatedTextTestData", DataAccessMethod.Sequential)]
        public void QuatedToUnquatedTextTest()
        {
            var dataDrivenTest = new DataDrivenTest<QuatedToUnquatedTextTestDataTestParams, QuatedToUnquatedTextTestDataExpectedResults>(this.TestContext);

            dataDrivenTest.ExecuteTest(() =>
            {
                var actualUnquatedText = DelimitedString_Accessor.QuatedToUnquatedText(dataDrivenTest.TestParams.QuatedText.Replace('_', ' '));

                Assert.AreEqual(dataDrivenTest.ExpectedResults.UnquatedText, actualUnquatedText);
            });
        }

        private class SplitTestDataTestParams
        {
            [DataTableColumnName("TestParamDelimitedText")]
            public string DelimitedText { get; set; }

            [DataTableColumnName("TestParamDelimiterChar")]
            public char DelimiterChar { get; set; }
        }

        private class SplitTestDataExpectedResults
        {
            [DataTableColumnName("ExpectedResultColumn1Text")]
            public string Column1Text { get; set; }

            [DataTableColumnName("ExpectedResultColumn2Text")]
            public string Column2Text { get; set; }

            [DataTableColumnName("ExpectedResultColumn3Text")]
            public string Column3Text { get; set; }
        }

        private class TryRemovePrefixTestDataTestParams
        {
            [DataTableColumnName("TestParamText")]
            public string Text { get; set; }

            [DataTableColumnName("TestParamPrefix")]
            public string Prefix { get; set; }
        }

        private class TryRemovePrefixTestDataExpectedResults
        {
            [DataTableColumnName("ExpectedResultRemoveResult")]
            public bool RemoveResult { get; set; }

            [DataTableColumnName("ExpectedResultTextWithRemovedPrefix")]
            public string TextWithRemovedPrefix { get; set; }
        }

        private class ParseFieldTestDataTestParams
        {
            [DataTableColumnName("TestParamFieldStartIndex")]
            public int FieldStartIndex { get; set; }

            [DataTableColumnName("TestParamDelimitedText")]
            public string DelimitedText { get; set; }

            [DataTableColumnName("TestParamDelimiterChar")]
            public char DelimiterChar { get; set; }

            [DataTableColumnName("TestParamEscapedEmptyAsZeroLengthString")]
            public bool EscapedEmptyAsZeroLengthString { get; set; }
        }

        private class ParseFieldTestDataExpectedResults
        {
            [DataTableColumnName("ExpectedFieldTextText")]
            public string ExpectedFieldTextText { get; set; }

            [DataTableColumnName("ExpectedNextFieldStartIndex")]
            public int ExpectedNextFieldStartIndex { get; set; }
        }

        private class QuatedToUnquatedTextTestDataTestParams
        {
            [DataTableColumnName("TestParamQuatedText")]
            public string QuatedText { get; set; }
        }

        private class QuatedToUnquatedTextTestDataExpectedResults
        {
            [DataTableColumnName("ExpectedUnquatedText")]
            public string UnquatedText { get; set; }
        }
    }
}
